package com.ce.pms.charge.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.IBusinessCodeDao;
import com.ce.pms.charge.dao.IChargeStaDao;
import com.ce.pms.charge.dao.IDebitTransDao;
import com.ce.pms.charge.dao.ILateFeeCountDao;
import com.ce.pms.charge.dao.ILatefeeDetailDao;
import com.ce.pms.charge.dao.IParameterDefDao;
import com.ce.pms.charge.dao.IPeriodDao;
import com.ce.pms.charge.dao.ISubAccountDao;
import com.ce.pms.charge.model.AbstractStaVersion;
import com.ce.pms.charge.model.BusinessCodeDomain;
import com.ce.pms.charge.model.ChargeInsertLateFeeDetailDO;
import com.ce.pms.charge.model.ChargeUpdateLateFeeDetailDO;
import com.ce.pms.charge.model.DebitTransDomain;
import com.ce.pms.charge.model.LateFeeModeDomain;
import com.ce.pms.charge.model.ParameterDefDomain;
import com.ce.pms.charge.model.PeriodDomain;
import com.ce.pms.charge.service.IDynamicModeCount;
import com.ce.pms.common.model.SysInfo;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.house.dao.IChargePrecinctDao;
import com.ce.pms.house.model.ChargePrecinctDomain;
import com.ce.pms.house.model.HouseDomain;
import com.ce.util.BlankUtil;
import com.ce.util.DateUtil;

/**
 * 功能描述: 支持浮动模式滞纳金计算类
 * <p>
 * 版权所有：中企动力
 * <p>
 * 未经本公司许可，不得以任何方式复制或使用本程序任何部分
 *
 * @author 胡煦 Create on:2008-9-19 Edit author: Edit on: 修改原因：
 *
 */

public class DynamicModeCount extends PmsBaseServiceImpl implements
		IDynamicModeCount {

	private final int PAGE_SIZE = 1000;

	private LateFeeModeDomain lateFeeModeDomain;

	private Map staVersionMap;

	private PeriodDomain periodDomain;

	private Date dateForCount;

	private Date dateForStart;

	private BusinessCodeDomain businessCodeDomain;

	private Map masterStaVerMap;

	private SysInfo sysInfo;

	public DynamicModeCount() {

	}

	/**
	 * 方法描述: 完成预处理: 1. 查询系统设定的滞纳金模式 2. 查询所有收费标准版本记录 3. 查询当前收费周期实例 4. 查询滞纳金交易码实例
	 *
	 * @author 胡煦 Create on:2008-9-19
	 * @param chargePrecinctId
	 * @return Edit author: Edit on: 修改原因：
	 */
	private void preProcess(Long chargePrecinctId) {
		// 查询系统设定的滞纳金模式
		lateFeeModeDomain = lateFeeCountDao.findLateFeeMode();
		// 查询所有收费标准版本记录及其对应的有效的版本
		staVersionMap = new HashMap();
		List<Object[]> satVersionList = chargeStaDao.queryChargeSatVersionAnd();
		for (Object[] staVersion : satVersionList) {
			staVersionMap.put(staVersion[0], staVersion[1]);
		}
		List<DebitTransDomain> list = debitTransDao.getTransDomainHasVer();
		// 查询应收交易其对应的有效的版本
		masterStaVerMap = new HashMap();
		for (DebitTransDomain debitTrans : list) {
			AbstractStaVersion staVersion = (AbstractStaVersion) staVersionMap.get(debitTrans.getStaVersion().getStaHisId());
			masterStaVerMap.put(debitTrans.getTransactionId(),staVersion);
		}
		// 查询当前收费周期实例
		PeriodDomain NowPeriod = periodDao.findPeriodByPrecinct(
				chargePrecinctId, "1").get(0);
		// 设置开始查询要计算滞纳金的收费周期
		// String period = periodDomain.getPeriod() -
		// lateFeeModeDomain.getDoingStep();
		dateForStart = DateUtil.convertStrToDate(NowPeriod.getPeriod()
				+ lateFeeModeDomain.getStartDate(), "yyyyMMdd");
		 Date dateForPeriod = DateUtil.addDate("MM", -lateFeeModeDomain.getStartStep(),
				 dateForStart);
		String period = DateUtil.convertDateToStr(dateForPeriod, "yyyyMMdd").substring(
				0, 6);
		periodDomain = periodDao.findPeriodByName(chargePrecinctId,period);
		if(!BlankUtil.isBlank(periodDomain)){
			// 设置计算滞纳金的开始日期
			Date dateForDo = DateUtil.convertStrToDate(periodDomain.getPeriod()
					+ lateFeeModeDomain.getDoingDate(), "yyyyMMdd");
			dateForCount = DateUtil.addDate("MM", lateFeeModeDomain.getDoingStep(),
					dateForDo);
			// 查询滞纳金交易码实例
			ParameterDefDomain parameterDefDomain = parameterDefDao.findUniqueBy(
					"pkey", "LATEFEE_CODE");
			businessCodeDomain = businessCodeDao.findById(parameterDefDomain
					.getPvalue());
		}

	}

	/**
	 * 方法描述: 完成滞纳金运算并收集持久化需求
	 *
	 * @author 胡煦 Create on:2008-9-19
	 * @param chargePrecinctId
	 * @return void Edit author: Edit on: 修改原因：
	 */
	public boolean doing() {
		sysInfo = createInfo(1l);
		List<ChargePrecinctDomain> resultList = chargePrecinctDao.findAll();
		for(ChargePrecinctDomain precinctDomain : resultList){
			// 预处理
			this.preProcess(precinctDomain.getKeyword());

			// 开始运算

			if (!BlankUtil.isBlank(periodDomain)) {
				// 处理已缴费滞纳金交易关联的滞纳金明细
				this.doForUpdate(precinctDomain.getKeyword());
				// 处理当天要开始计算滞纳金的欠费数据
				this.doForInsert(precinctDomain.getKeyword());

			}
		}
		return true;
	}

	/**
	 * 方法描述: 处理已缴费滞纳金交易关联的滞纳金明细
	 *
	 * @author 胡煦 Create on:2008-9-25
	 * @param latefeeDetailBaseAmt
	 * @param accountTotal
	 * @param dereteTotal
	 * @param adjustTotal
	 * @param latefeeTotal
	 * @param tempMasterTransId
	 * @param tempChargeAccountId
	 * @param chargePrecinctId,lateFeeModeDomain,
	 *            businessCodeDomain, staVersionMap, periodDomain
	 * @return void Edit author: Edit on: 修改原因：
	 */
	private void doForUpdate(Long chargePrecinctId) {

		int pageNo = 1;
		// 查询已生成滞纳金的欠费交易
		List<ChargeUpdateLateFeeDetailDO> updateLateFeeList = null;
		Map<Long, BigDecimal> accountMap = new HashMap<Long, BigDecimal>(); // 收集对ChargeAccountDomain的更新
		List<Object[]> updateLatefeeDetailListForLatefee = new ArrayList<Object[]>(); // 收集对LatefeeDetail的更新
		List<Object[]> updateLatefeeDetailListForValidity = new ArrayList<Object[]>();// 收集对LatefeeDetail的更新
		List<Object[]> insertLatefeeDetailList = new ArrayList<Object[]>(); // 收集对LatefeeDetail的新增
		List<Object[]> updateDebitTransList = new ArrayList<Object[]>(); // 收集对DebitTransDomain的更新
		//查询当天生成通知单的房屋(记帐策略依附的房屋)
		Set<Long> houseIdSet = new HashSet<Long>();
		List<Long> houseIdList = lateFeeCountDao.queryInNoticHouse(chargePrecinctId,this.getDate());
		houseIdSet.addAll(houseIdList);
		// 临时,用于处理相同帐号被页数截断问题
		List<ChargeUpdateLateFeeDetailDO> tempList = new ArrayList<ChargeUpdateLateFeeDetailDO>();
		do {
			updateLateFeeList = lateFeeCountDao.queryMakedLateFeeList(pageNo++,
					PAGE_SIZE, chargePrecinctId);
			if (updateLateFeeList.size()>0) {

				// 滞纳金计算算法循环开始
				for (int i = 0; i < updateLateFeeList.size(); i++) {
					ChargeUpdateLateFeeDetailDO o1 = (ChargeUpdateLateFeeDetailDO) updateLateFeeList
							.get(i);

					if (this.isSameAccountFor(updateLateFeeList, null, i)
							&& i == PAGE_SIZE - 1) {
						tempList.add(o1);
						updateLateFeeList = lateFeeCountDao
								.queryMakedLateFeeList(pageNo++, PAGE_SIZE,
										chargePrecinctId);
						i = -1;
					} else if (this.isLastSameAccountFor(updateLateFeeList,
							null, i)) {

						doingForUpdate(tempList, houseIdSet, accountMap,
								updateLatefeeDetailListForLatefee,
								updateLatefeeDetailListForValidity,
								insertLatefeeDetailList, updateDebitTransList);
						tempList.clear();
						tempList.add(o1);
					} else if(updateLateFeeList.size() != PAGE_SIZE && i == updateLateFeeList.size() - 1){
						tempList.add(o1);
						doingForUpdate(tempList, houseIdSet, accountMap,
								updateLatefeeDetailListForLatefee,
								updateLatefeeDetailListForValidity,
								insertLatefeeDetailList, updateDebitTransList);
						}else{
						tempList.add(o1);
					}
				}
			}
		} while (updateLateFeeList != null
				&& updateLateFeeList.size() == PAGE_SIZE);

		// 调用批处理更新数据表
		// call batch update for
		// updateLatefeeListForLatefee;updateLatefeeListForValidity
		// insertLatefeeDetailList;updateDebitTransList;accountMap
		this.doInsertOrUpdate(accountMap, insertLatefeeDetailList, null,
				updateLatefeeDetailListForLatefee,
				updateLatefeeDetailListForValidity, updateDebitTransList);
	}

	/**
	 * 方法描述: 处理已缴费滞纳金交易关联的滞纳金明细具体步骤
	 *
	 * @author 胡煦 Create on:2008-10-7
	 * @param updateDebitTransList
	 * @param insertLatefeeDetailList
	 * @param updateLatefeeDetailListForValidity
	 * @param updateLatefeeDetailListForLatefee
	 * @param accountMap
	 * @param houseList
	 * @param tempList
	 * @param nameStr：查询条件班级名称
	 * @return 返回当前页的查询结果 Edit author: Edit on: 修改原因：
	 */
	private void doingForUpdate(List<ChargeUpdateLateFeeDetailDO> tempList,
			Set houseSet, Map<Long, BigDecimal> accountMap,
			List<Object[]> updateLatefeeDetailListForLatefee,
			List<Object[]> updateLatefeeDetailListForValidity,
			List<Object[]> insertLatefeeDetailList,
			List<Object[]> updateDebitTransList) {
		// 收费账户Id
		Long tempChargeAccountId = -1L;
		// 主交易Id
		Long tempMasterTransId = -1L;
		// 欠费滞纳金计算金额总计
		BigDecimal latefeeTotal = new BigDecimal(0.00);
		// 欠费调整金额总计
		BigDecimal adjustTotal = new BigDecimal(0.00);
		// 欠费减免金额总计
		BigDecimal dereteTotal = new BigDecimal(0.00);
		// 账户修改金额总计
		BigDecimal accountTotal = new BigDecimal(0.00);
		// 滞纳金明细读取的本金
		BigDecimal latefeeDetailBaseAmt = new BigDecimal(0.00);
		for (int i = 0; i < tempList.size(); i++) {
			ChargeUpdateLateFeeDetailDO o1 = tempList.get(i);

			if(o1.getBaseAmt().compareTo(new BigDecimal(0)) != -1){

				// 当前生效的版本
				AbstractStaVersion staHis = (AbstractStaVersion) masterStaVerMap
						.get(o1.getMasterTransId());
				Long temp1 = o1.getChargeAccountId();
				// 如果不收取滞纳金,则返回
				if (SysrefcodeDO.CONSTANTS_DIGITAL_ZERO.equals(staHis
						.getLatefeeSelect())){

					// 处理相同账户数据的信息
					if (tempList.size() == (i + 1)
							|| !((ChargeUpdateLateFeeDetailDO) tempList.get(i + 1))
									.getChargeAccountId().equals(temp1)) {
						if(accountTotal.compareTo(new BigDecimal(0.00)) == 1){
							// 记录账户更新金额
							accountMap.put(temp1, accountTotal);

							// 重置分账户统计参量
							accountTotal = new BigDecimal(0.00);
						}
					}
					// 重置分账户指针
					tempChargeAccountId = -1L ;
					continue;
				}
				if (tempChargeAccountId == -1L || temp1.equals(tempChargeAccountId)) {
					Long temp2 = o1.getMasterTransId();
					latefeeDetailBaseAmt = o1.getBaseAmt();
					// 相同收费项目的主交易及衍生交易
					if (tempMasterTransId == -1 || temp2.equals(tempMasterTransId)) {
						if (!(o1.getBizCodeId().equals(
								businessCodeDomain.getKeyword()))) {
							latefeeTotal = latefeeTotal.add(o1.getDebit());
						}
						if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_ADJUSTMENT.equals(o1
								.getClazzCode())) { // 统计调整
							adjustTotal = adjustTotal.add(o1.getDebit());
						}
						// 过滤滞纳金减免
						if (!o1.getBizCodeId().equals(
								businessCodeDomain.getKeyword())
								&& o1.getClazzCode().equals(
										SysrefcodeDO.FEE_TRANSACTION_CLAZZ_RELIEF)) {
							dereteTotal = dereteTotal.add(o1.getDebit());
						}
					}

					// 赋值本次收费项目主交易Id
					tempMasterTransId = temp2;

					// 最后处理相同收费项目数据的信息(备注：要一定是同一个账户)
					if (tempList.size() == (i + 1)
							|| !((ChargeUpdateLateFeeDetailDO) tempList.get(i + 1))
									.getMasterTransId().equals(temp2)) {

						// 如果计算滞纳金金额发生变化或者统计数据对应的房屋已生成通知单
						if (!latefeeDetailBaseAmt.equals(latefeeTotal)
								|| houseSet.contains(o1.getHouseId())) {
							// 计算欠费数据滞纳金
							Date endDate = DateUtil.addDate(o1.getEndDate(), 1);
							int dateToUse = DateUtil.getDays(endDate, this.getDate()) + 1;
							BigDecimal happenAmt = (((latefeeTotal.multiply(
									staHis.getRate()).multiply(
									new BigDecimal(0.01)))).setScale(2, RoundingMode.HALF_UP)).multiply(
									new BigDecimal(dateToUse));
							// 记录对目前滞纳金明细的修改(是否当前段=0)
							Object[] validitys = new Object[] {
									SysrefcodeDO.CONSTANTS_DIGITAL_ZERO,
									o1.getLateDetailId() };
							updateLatefeeDetailListForValidity.add(validitys);
							// 收集对LatefeeDetail的新增
							Object[] latefeeDetailObjs = new Object[] {
									dereteTotal, adjustTotal, happenAmt,
									latefeeTotal, staHis.getRate(),endDate,
									this.getDate(), o1.getLateFeeTransId(),
									SysrefcodeDO.CONSTANTS_DIGITAL_ONE, temp2 };
							// 记录新增滞纳金明细
							insertLatefeeDetailList.add(latefeeDetailObjs);
							// 记录更新DebitTransDomain
							Object[] debitTranObjs = new Object[] { happenAmt,
									o1.getLateFeeTransId() };
							updateDebitTransList.add(debitTranObjs);
							// 累计分项统计结果
							accountTotal = accountTotal.add(happenAmt);
						} else {// 计算滞纳金金额未发生变化并且统计数据对应的房屋未生成通知单
							// 计算欠费数据滞纳金
							Date endDate = o1.getEndDate();
							int dateToUse = DateUtil.getDays(endDate, this.getDate());
							BigDecimal happenAmt = (((latefeeTotal.multiply(
													staHis.getRate()).multiply(
											new BigDecimal(0.01)))).setScale(2, RoundingMode.HALF_UP)).multiply(
											new BigDecimal(dateToUse));
							// 计算并记录更新的滞纳金金额
							Object[] updateLatefeeObjs = new Object[] { happenAmt,
									this.getDate(), o1.getLateDetailId() };
							updateLatefeeDetailListForLatefee
									.add(updateLatefeeObjs);
							// 记录更新DebitTransDomain
							Object[] debitTransDoObjs = new Object[] { happenAmt,
									o1.getLateFeeTransId() };
							updateDebitTransList.add(debitTransDoObjs);
							// 累计分项统计结果
							accountTotal = accountTotal.add(happenAmt);
						}
						// 重置分项统计参量
						latefeeTotal = new BigDecimal(0.00);
						adjustTotal = new BigDecimal(0.00);
						dereteTotal = new BigDecimal(0.00);
						// 重置分享指针
						tempMasterTransId = -1L;

					}

					// 赋值本次读取的账户Id
					tempChargeAccountId = temp1;

				}
				// 最后处理相同账户数据的信息
				if (tempList.size() == (i + 1)
						|| !((ChargeUpdateLateFeeDetailDO) tempList.get(i + 1))
								.getChargeAccountId().equals(tempChargeAccountId)) {
					if(accountTotal.compareTo(new BigDecimal(0.00)) == 1){
						// 记录账户更新金额
						accountMap.put(temp1, accountTotal);

						// 重置分账户统计参量
						accountTotal = new BigDecimal(0.00);
					}
					// 重置分账户指针
					tempChargeAccountId = -1L;
				}
			}

		}

	}

	/**
	 * 方法描述: 处理当天要开始计算滞纳金的欠费数据
	 *
	 * @author 胡煦 Create on:2008-9-25
	 * @param accountTotal
	 * @param dereteTotal
	 * @param adjustTotal
	 * @param latefeeTotal
	 * @param tempMasterTransId
	 * @param tempChargeAccountId
	 * @param latefeeDetailBaseAmt
	 * @param chargePrecinctId,lateFeeModeDomain,
	 *            businessCodeDomain, staVersionMap, periodDomain
	 * @return void Edit author: Edit on: 修改原因：
	 */
	private void doForInsert(Long chargePrecinctId) {
		int pageNo = 1;
		List<ChargeInsertLateFeeDetailDO> insertLateFeeList = null;
		Map<Long, BigDecimal> accountMap = new HashMap<Long, BigDecimal>(); // 收集对ChargeAccountDomain的更新
		List<Object[]> insertLatefeeDetailList = new ArrayList<Object[]>(); // 收集对LatefeeDetail的新增
		List<Object[]> insertTraRtrList = new ArrayList<Object[]>(); // 收集对TraRtra的新增;
		// 临时,用于处理相同帐号被页数截断问题
		List<ChargeInsertLateFeeDetailDO> tempList = new ArrayList<ChargeInsertLateFeeDetailDO>();
		do {
			// 处理当天要开始计算滞纳金的欠费数据
			if (!BlankUtil.isBlank(lateFeeModeDomain)
					&& !BlankUtil.isBlank(lateFeeModeDomain.getStartDate())) {

				if (this.getDate().compareTo(dateForStart) != -1) {// 当日期为开始计算日的日子时,开始运算
					// 查询要求开始计算滞纳金的欠费数据
					insertLateFeeList = lateFeeCountDao.queryUnMakeLateFeeList(
							pageNo++, PAGE_SIZE, chargePrecinctId, periodDomain
									.getKeyword());
					if (insertLateFeeList.size() > 0) {
						// 滞纳金计算算法循环开始
						for (int i = 0; i < insertLateFeeList.size(); i++) {
							ChargeInsertLateFeeDetailDO o1 = (ChargeInsertLateFeeDetailDO) insertLateFeeList
									.get(i);

							if (this.isSameAccountFor(null, insertLateFeeList,
									i)
									&& i == PAGE_SIZE - 1) {
								tempList.add(o1);
								insertLateFeeList = lateFeeCountDao
										.queryUnMakeLateFeeList(pageNo++,
												PAGE_SIZE, chargePrecinctId,
												periodDomain.getKeyword());
								if(insertLateFeeList.size()==0){
									doingForInsert(tempList, accountMap,
											insertLatefeeDetailList,
											insertTraRtrList);
									tempList.clear();
								}else{
									i = -1;
								}
							} else if (this.isLastSameAccountFor(null,
									insertLateFeeList, i)) {

								doingForInsert(tempList, accountMap,
										insertLatefeeDetailList,
										insertTraRtrList);
								tempList.clear();
								tempList.add(o1);
							} else if(insertLateFeeList.size() != PAGE_SIZE && i == insertLateFeeList.size() - 1){
								tempList.add(o1);
								doingForInsert(tempList, accountMap,
										insertLatefeeDetailList,
										insertTraRtrList);
								tempList.clear();
							}else{
								tempList.add(o1);
							}
						}
					}
				}
			}
		} while (insertLateFeeList != null
				&& insertLateFeeList.size() == PAGE_SIZE);
		// 调用批处理更新数据表
		// call batch update for
		// insertLatefeeDetailList2;insertTraRtrList;accountMap
		this.doInsertOrUpdate(accountMap, insertLatefeeDetailList,
				insertTraRtrList, null, null, null);

	}

	/**
	 * 方法描述: 处理当天要开始计算滞纳金的欠费数据具体步骤
	 *
	 * @author 胡煦 Create on:2008-10-7
	 * @param insertTraRtrList
	 * @param insertLatefeeDetailList
	 * @param accountMap
	 * @param tempList
	 * @return void Edit author: Edit on: 修改原因：
	 */
	private void doingForInsert(List<ChargeInsertLateFeeDetailDO> tempList,
			Map<Long, BigDecimal> accountMap,
			List<Object[]> insertLatefeeDetailList,
			List<Object[]> insertTraRtrList) {

		// 收费账户Id
		Long tempChargeAccountId = -1L;
		// 主交易Id
		Long tempMasterTransId = -1L;
		// 欠费滞纳金计算金额总计
		BigDecimal latefeeTotal = new BigDecimal(0.00);
		// 欠费调整金额总计
		BigDecimal adjustTotal = new BigDecimal(0.00);
		// 欠费减免金额总计
		BigDecimal dereteTotal = new BigDecimal(0.00);
		// 账户修改金额总计
		BigDecimal accountTotal = new BigDecimal(0.00);
		for (int i = 0; i < tempList.size(); i++) {
			// 取出一笔欠费数据记录
			ChargeInsertLateFeeDetailDO o1 = tempList.get(i);

			if(o1.getMaterDebit().compareTo(new BigDecimal(0)) == 1){
				// 当前生效的版本
				AbstractStaVersion staHis = (AbstractStaVersion) masterStaVerMap
						.get(o1.getCompositeID().masterTransId);
				Long temp1 = o1.getChargeAccountId();
				// 如果不收取滞纳金,则返回
				if (SysrefcodeDO.CONSTANTS_DIGITAL_ZERO.equals(staHis
						.getLatefeeSelect())){
					// 处理相同账户数据的信息
					if (tempList.size() == (i + 1)
							|| !((ChargeInsertLateFeeDetailDO) tempList.get(i + 1))
									.getChargeAccountId().equals(temp1)) {
						if(accountTotal.compareTo(new BigDecimal(0.00)) == 1){
							// 记录账户更新金额
							accountMap.put(temp1, accountTotal);

							// 重置分账户统计参量
							accountTotal = new BigDecimal(0.00);
						}
					}
					// 重置分账户指针
					tempChargeAccountId = -1L ;
					continue;
				}
				// 相同账户
				if (tempChargeAccountId == -1L || temp1.equals(tempChargeAccountId)) {

					Long temp2 = o1.getCompositeID().getMasterTransId();

					// 相同收费项目的主交易及衍生交易
					if (tempMasterTransId == -1l || temp2.equals(tempMasterTransId)) {

						if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_ADJUSTMENT.equals(o1
								.getSecondClazzCode())) { // 统计调整
							adjustTotal = adjustTotal.add(o1.getSecondDebit());
							//latefeeTotal = latefeeTotal.add(o1.getSecondDebit());
						}
						if (SysrefcodeDO.FEE_TRANSACTION_CLAZZ_RELIEF.equals(o1
								.getSecondClazzCode())) { // 统计减免
							dereteTotal = dereteTotal.add(o1.getSecondDebit());
							//latefeeTotal = latefeeTotal.add(o1.getSecondDebit());
						}

					}
					// 赋值本次收费项目主交易Id
					tempMasterTransId = temp2;
					// 最后处理相同收费项目数据的信息(备注：要一定是同一个账户)
					if (tempList.size() == (i + 1)
							|| !((ChargeInsertLateFeeDetailDO) tempList.get(i + 1))
									.getCompositeID().getMasterTransId().equals(
											temp2)) {
						// 计算欠费数据滞纳金
						latefeeTotal = o1.getMaterDebit().add(adjustTotal).add(dereteTotal);
						int dateToUse = DateUtil.getDays(dateForCount, this.getDate()) + 1;
						BigDecimal happenAmt = (((latefeeTotal.multiply(
								staHis.getRate()).multiply(
										new BigDecimal(0.01)))).setScale(2, RoundingMode.HALF_UP)).multiply(
										new BigDecimal(dateToUse));

						// 插入滞纳金交易
						DebitTransDomain latefeetrans = new DebitTransDomain();
						latefeetrans.setPeriod(periodDomain);
						latefeetrans.setDebit(happenAmt);
						// latefeetrans.setHouse(houseDao.findById(o1.getHouseId()));
						latefeetrans.setHouse(new HouseDomain(o1.getHouseId()));
						latefeetrans.setBusinessCode(businessCodeDomain);
						latefeetrans.setBindingAccount(subAccountDao
								.loadById(temp1));
						latefeetrans
								.setClazz(SysrefcodeDO.FEE_TRANSACTION_CLAZZ_LATEFEES);
						latefeetrans
								.setStatuz(SysrefcodeDO.FEE_TRANSACTION_STATUZ_NOTPAY);
						latefeetrans.setSysInfo(sysInfo);
						latefeetrans
								.setStaVersion((AbstractStaVersion) staVersionMap
										.get(o1.getStaHisId()));
						latefeetrans.setMTransId(temp2);
						latefeetrans = debitTransDao.saveObject(latefeetrans);
						// 收集对TraRtra的新增
						Object[] insertTraRtrObjs = new Object[] {
								tempMasterTransId, latefeetrans.getTransactionId(),
								SysrefcodeDO.FEE_TRA_R_TRA_RELATION_TYPE_LATEFEES };
						insertTraRtrList.add(insertTraRtrObjs);
						// 收集对LatefeeDetail的新增
						Object[] objects = new Object[] { dereteTotal, adjustTotal,
								happenAmt, latefeeTotal, staHis.getRate(),
								dateForCount,this.getDate(),
								latefeetrans.getTransactionId(),
								SysrefcodeDO.CONSTANTS_DIGITAL_ONE, temp2 };
						insertLatefeeDetailList.add(objects);

						// 重置分项统计参量
						latefeeTotal = new BigDecimal(0.00);
						adjustTotal = new BigDecimal(0.00);
						dereteTotal = new BigDecimal(0.00);
						// 重置分享指针
						tempMasterTransId = -1L;

						// 统计账户金额变化
						accountTotal = accountTotal.add(happenAmt);

					}
					// 赋值本次读取的账户Id
					tempChargeAccountId = temp1;

				}
				// 最后处理相同账户数据的信息
				if (tempList.size() == (i + 1)
						|| !((ChargeInsertLateFeeDetailDO) tempList.get(i + 1))
								.getChargeAccountId().equals(tempChargeAccountId)) {

					if(accountTotal.compareTo(new BigDecimal(0.00)) == 1){
						// 记录账户更新金额
						accountMap.put(temp1, accountTotal);

						// 重置分账户统计参量
						accountTotal = new BigDecimal(0.00);
					}
					// 重置分账户指针
					tempChargeAccountId = -1L;
				}

			}


		}
	}


	/**
	 * 方法描述: 批处理更新数据表方法
	 *
	 * @author 胡煦 Create on:2008-9-25
	 * @param nameStr：查询条件班级名称
	 * @return 返回当前页的查询结果 Edit author: Edit on: 修改原因：
	 */
	private void doInsertOrUpdate(Map accountMap, List insertLatefeeDetailList,
			List insertTraRtrList, List updateLatefeeDetailListForLatefee,
			List updateLatefeeDetailListForValidity, List updateDebitTransList) {
		List accountIdList = this.changeMap2List(accountMap);
		if(!BlankUtil.isBlank(insertLatefeeDetailList)&&insertLatefeeDetailList.size() > 0){
			latefeeDetailDao.batchInsertLatefeeDetails(insertLatefeeDetailList);
		}
		if(!BlankUtil.isBlank(updateLatefeeDetailListForLatefee)&&updateLatefeeDetailListForLatefee.size() >0){
			latefeeDetailDao
			.batchUpdateForLatefee(updateLatefeeDetailListForLatefee);
		}
		if(!BlankUtil.isBlank(updateLatefeeDetailListForValidity)&&updateLatefeeDetailListForValidity.size() > 0){
			latefeeDetailDao
			.batchUpdateLatefeesForValidity(updateLatefeeDetailListForValidity);
		}
		if(!BlankUtil.isBlank(updateDebitTransList)&&updateDebitTransList.size() > 0){
			lateFeeCountDao.batchUpdateDebitTransList(updateDebitTransList);
		}
		if(!BlankUtil.isBlank(accountIdList)&&accountIdList.size() > 0){
			lateFeeCountDao.batchUpdateSubAccountBalance(accountIdList);
		}
		if(!BlankUtil.isBlank(insertTraRtrList)&&insertTraRtrList.size() > 0){
			lateFeeCountDao.batchInsertTraRtrList(insertTraRtrList);
		}

	}

	/**
	 * 功能描述:判断当前的子帐户和上一个是否相同<br>
	 *
	 * @param updateLateFeeList
	 *            or insertLateFeeList
	 * @param index
	 * @return boolean<br>
	 * Create author:胡煦<br>
	 * Create on:2008-10-7<br>
	 * Edit author:<br>
	 * Edit on:<br>
	 * Why:<br>
	 */
	private boolean isSameAccountFor(
			List<ChargeUpdateLateFeeDetailDO> updateLateFeeList,
			List<ChargeInsertLateFeeDetailDO> insertLateFeeList, int index) {
		if (!BlankUtil.isBlank(updateLateFeeList)) {
			return index > 0
					&& updateLateFeeList.get(index).getChargeAccountId()
							.equals(
									updateLateFeeList.get(index - 1)
											.getChargeAccountId());
		} else if (!BlankUtil.isBlank(insertLateFeeList)) {
			return index > 0
					&& insertLateFeeList.get(index).getChargeAccountId()
							.equals(
									insertLateFeeList.get(index - 1)
											.getChargeAccountId());
		}
		return false;
	}

	/**
	 * 功能描述:判断是否最后一个相同的帐号<br>
	 *
	 * @param updateLateFeeList
	 *            or insertLateFeeList
	 * @param index
	 * @return boolean<br>
	 *         Create author:胡煦<br>
	 *         Create on:2008-10-7<br>
	 *         Edit author:<br>
	 *         Edit on:<br>
	 *         Why:<br>
	 */
	private boolean isLastSameAccountFor(
			List<ChargeUpdateLateFeeDetailDO> updateLateFeeList,
			List<ChargeInsertLateFeeDetailDO> insertLateFeeList, int index) {
		if (!BlankUtil.isBlank(updateLateFeeList)) {
			boolean notLastPage = updateLateFeeList.size() == PAGE_SIZE;
			boolean isLastItem = (index == (updateLateFeeList.size() - 1));
			boolean result2 = (updateLateFeeList.size()>1&&index == updateLateFeeList.size() - 1 && !updateLateFeeList
					.get(index).getChargeAccountId().equals(
							updateLateFeeList.get(index - 1)
									.getChargeAccountId()));

			return (isLastItem || result2) && notLastPage;
		} else if (!BlankUtil.isBlank(insertLateFeeList)) {
			boolean notLastPage = insertLateFeeList.size() == PAGE_SIZE;
			boolean isLastItem = (index == (insertLateFeeList.size() - 1));
			boolean result2 = (insertLateFeeList.size()>1&&index == insertLateFeeList.size() - 1 && !insertLateFeeList
					.get(index).getChargeAccountId().equals(
							insertLateFeeList.get(index - 1)
									.getChargeAccountId()));

			return (isLastItem || result2) && notLastPage;
		}
		return false;

	}

	private List changeMap2List(Map accountMap) {
		List<Object[]> accountIdList = new ArrayList<Object[]>();
		for (Object accountId : accountMap.keySet()) {
			Object[] accountObjs = new Object[] { accountMap.get(accountId),
					accountId };
			accountIdList.add(accountObjs);
		}
		return accountIdList;
	}

	private ILateFeeCountDao lateFeeCountDao;

	private IChargeStaDao chargeStaDao;

	private IPeriodDao periodDao;

	private IParameterDefDao parameterDefDao;

	private IBusinessCodeDao businessCodeDao;

	private ILatefeeDetailDao latefeeDetailDao;

	private IDebitTransDao debitTransDao;

	private ISubAccountDao subAccountDao;

	private IChargePrecinctDao chargePrecinctDao;

	/**
	 * @param lateFeeCountDao
	 *            the lateFeeCountDao to set
	 */
	public void setLateFeeCountDao(ILateFeeCountDao lateFeeCountDao) {
		this.lateFeeCountDao = lateFeeCountDao;
	}

	/**
	 * @param chargeStaDao
	 *            the chargeStaDao to set
	 */
	public void setChargeStaDao(IChargeStaDao chargeStaDao) {
		this.chargeStaDao = chargeStaDao;
	}

	/**
	 * @param periodDao
	 *            the periodDao to set
	 */
	public void setPeriodDao(IPeriodDao periodDao) {
		this.periodDao = periodDao;
	}

	/**
	 * @param parameterDefDao
	 *            the parameterDefDao to set
	 */
	public void setParameterDefDao(IParameterDefDao parameterDefDao) {
		this.parameterDefDao = parameterDefDao;
	}

	/**
	 * @param businessCodeDao
	 *            the businessCodeDao to set
	 */
	public void setBusinessCodeDao(IBusinessCodeDao businessCodeDao) {
		this.businessCodeDao = businessCodeDao;
	}

	/**
	 * @param latefeeDetailDao
	 *            the latefeeDetailDao to set
	 */
	public void setLatefeeDetailDao(ILatefeeDetailDao latefeeDetailDao) {
		this.latefeeDetailDao = latefeeDetailDao;
	}

	/**
	 * @param debitTransDao
	 *            the debitTransDao to set
	 */
	public void setDebitTransDao(IDebitTransDao debitTransDao) {
		this.debitTransDao = debitTransDao;
	}

	/**
	 * @param subAccountDao
	 *            the subAccountDao to set
	 */
	public void setSubAccountDao(ISubAccountDao subAccountDao) {
		this.subAccountDao = subAccountDao;
	}
	/**
	 * @param chargePrecinctDao the chargePrecinctDao to set
	 */
	public void setChargePrecinctDao(IChargePrecinctDao chargePrecinctDao) {
		this.chargePrecinctDao = chargePrecinctDao;
	}
}
